package com.pclong.doudizhu.server.demo1;
import java.util.*;

/**
 * Description:
 * </br>Copyright (C), 2005-2009, KK
 * </br>This program is protected by copyright laws.
 * </br>Program name: DouDiZhu
 * </br>Date: 12/10/09
 * @author kk
 * @version 1.0
 */

enum PokerSuiteEnum {
	HEART("Heart"), SPADE("Spade"), DIAMOND("Diamond"), CLUB("Club"),
	RED("Red"), BLACK("Black");
	
	private final String name;
	private PokerSuiteEnum(String name)
	{
		this.name = name;
	}
	
	public String getName()
	{
		return this.name;
	}
}

enum PokerValueEnum {
	ACE("A"), KING("K"), QUEEN("Q"), JACK("J"), TEN("10"), NINE("9"), EIGHT("8"),
	SEVEN("7"), SIX("6"), FIVE("5"), FOUR("4"), THREE("3"), TWO("2"), JOKER("Joker");
	
	private final String name;
	private PokerValueEnum(String name)
	{
		this.name = name;
	}
	
	public String getName()
	{
		return this.name;
	}
}

class PokerCard {
	protected PokerSuiteEnum s;
	protected PokerValueEnum v;
	
	public PokerCard () {}
	public PokerCard (PokerSuiteEnum s, PokerValueEnum v)
	{
		this.s = s;
		this.v = v;
	}
	
	public PokerSuiteEnum getSuiteEnum()
	{
		return this.s;
	}
	
	public PokerValueEnum getValueEnum()
	{
		return this.v;
	}
	
	public void printCard()
	{
		System.out.print(s.getName()+v.getName());
	}
}

class DDZPokerCard extends PokerCard{
	public final int value;
	
	public DDZPokerCard(PokerSuiteEnum s, PokerValueEnum v)
	{
		super(s, v);
		
		if(v.getName().compareTo("Joker") == 0)
		{
			if(s.getName().compareTo("Red") == 0)
				value = 17;
			else
				value = 16;
		}
		else if(v.getName().compareTo("2") == 0)
			value = 15;
		else if(v.getName().compareTo("A") == 0)
			value = 14;
		else if(v.getName().compareTo("K") == 0)
			value = 13;
		else if(v.getName().compareTo("Q") == 0)
			value = 12;
		else if(v.getName().compareTo("J") == 0)
			value = 11;
		else
			value = Integer.parseInt(v.getName());
	}
}

// a collection of DDZPokerCard
class DDZCards {
	private List<DDZPokerCard> cards = new ArrayList<DDZPokerCard>();
	
	public DDZCards() {}
	public DDZCards(List<DDZPokerCard> c)
	{
		addCardAll(c);
	}
	public DDZCards(DDZPokerCard[] c)
	{
		for(DDZPokerCard e : c)
			addCard(e);
	}
	
	// print the cards
	public void print()
	{
		for(DDZPokerCard c : this.cards)
		{
			c.printCard();
			System.out.print(" ");
		}
	}
	
	// shuffle the cards
	public void shuffle()
	{
		Collections.shuffle(this.cards);
	}
	
	// sort the cards by value
	class sortByValue implements Comparator<DDZPokerCard>{
		public int compare(DDZPokerCard c1, DDZPokerCard c2)
		{
			if(c1.value > c2.value)
				return -1;
			else if(c1.value == c2.value)
				return 0;
			else
				return 1;
		}
	}
	public void sort()
	{
		Collections.sort(this.cards, new sortByValue());
	}
	
	public int getLength()
	{
		return this.cards.size();
	}
	
	public List<DDZPokerCard> getAllCards()
	{
		return this.cards;
	}
	
	public DDZPokerCard getCardAt(int index)
	{
		if(index>-1 && index<this.cards.size())
			return this.cards.get(index);
		else
			return null;
	}
	
	public DDZPokerCard deleteCardAt(int index)
	{
		if(index>-1 && index<this.cards.size())
			return this.cards.remove(index);
		else
			return null;
	}
	
	public boolean deleteCard(DDZPokerCard c)
	{
		return this.cards.remove(c);
	}
	
	public boolean deleteCardAll(List<DDZPokerCard> c)
	{
		return this.cards.removeAll(c);
	}
	
	public boolean addCard(DDZPokerCard c)
	{
		return this.cards.add(c);
	}
	
	public boolean addCardAll(List<DDZPokerCard> c)
	{
		return this.cards.addAll(c);
	}
	
	public boolean absorb(DDZCards target)
	{
		return addCardAll(target.getAllCards());
	}
	
	public DDZCards getCardsBetween(int from, int to)
	{
		DDZCards result = new DDZCards();
		if(from <0 || from>to)
			return result;
		if(from == to)
		{
			result.addCard(this.getCardAt(from));
			return result;
		}
		for(int i=from; i<to+1; i++)
			result.addCard(this.getCardAt(i));
		return result;
	}
	
	/**
	 * Description: find the number of cards with the same value
	 * @param value DDZPokerCard.value
	 * @return number of DDZPokerCard with the same value
	 */
	public int findCardByValue(int value)
	{
		int n=0;
		if(value>17 || value<3)
			return 0;
		for(int i=0; i<getLength(); i++)
			if(getCardAt(i).value == value)
				n++;
		return n;
	}
	/**
	 * Description: find the first show up of a card, which is identified by its value
	 * @param value the value of card you want to search
	 * @return -1:not found, else return its index
	 */
	public int findCardByFirstlySee(int value)
	{
		if(value>17 || value<3)
			return -1;
		sort();
		int i;
		for(i=0; i<getLength(); i++)
			if(getCardAt(i).value == value)
				break;
		if(i == getLength())
			return -1;
		else
			return i;
	}
}

public class Poker {
	private final int NumOfCards = 54;
	private DDZPokerCard[] InitalCards;
	private DDZCards ActualCards;
	
	public Poker ()
	{
		InitalCards = new DDZPokerCard[NumOfCards];
		int n=0;
		for(PokerSuiteEnum s : PokerSuiteEnum.values())
		{
			if(s.equals(PokerSuiteEnum.RED)||s.equals(PokerSuiteEnum.BLACK))
			{
				InitalCards[n] = new DDZPokerCard(s, PokerValueEnum.JOKER);
				n++;
			}
			else
			{
				for(PokerValueEnum v : PokerValueEnum.values())
				{
					if(!v.equals(PokerValueEnum.JOKER))
					{
						InitalCards[n] = new DDZPokerCard(s, v);
						n++;
					}
				}
			}
		}
		ActualCards = new DDZCards(InitalCards);
	}
	
	public int getNumOfCards()
	{
		return NumOfCards;
	}

	public void printPoker()
	{
		for(int i=0; i<NumOfCards; i++)
			ActualCards.print();
	}
	
	public void shuffle()
	{
		this.ActualCards.shuffle();
	}
	
	public void sort()
	{
		this.ActualCards.sort();
	}
	
	public DDZPokerCard getCardAt(int index)
	{
		return this.ActualCards.getCardAt(index);
	}
	
	//TODO
	public void test()
	{
		shuffle();
		DDZCards c = new DDZCards();
		for(int i=0; i<17; i++)
			c.addCard(this.ActualCards.getCardAt(i));
		c.sort();
		c.print();
		System.out.print("\n");
		
		DDZPokerCard p1 = new DDZPokerCard(PokerSuiteEnum.BLACK, PokerValueEnum.SEVEN);
		DDZPokerCard p2 = new DDZPokerCard(PokerSuiteEnum.BLACK, PokerValueEnum.SIX);
		DDZPokerCard p3 = new DDZPokerCard(PokerSuiteEnum.BLACK, PokerValueEnum.FIVE);
		DDZPokerCard p4 = new DDZPokerCard(PokerSuiteEnum.BLACK, PokerValueEnum.FOUR);
		DDZPokerCard p5 = new DDZPokerCard(PokerSuiteEnum.BLACK, PokerValueEnum.THREE);
		DDZPokerCard[] p = {p1, p2, p3, p4, p5};
		
		DDZHandCards h = new DDZHandCards(new DDZCards(p));
		
		DDZHandCards result = Rules.findBigger(c, h, true);
		result.print();
		System.out.print("\n");
	}
}